/*
* Change Logs:
* Date           Author       Notes
* 2022-01-15     chenbin
*/
#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include "rtthread.h"
#include "rtdevice.h"

#define DBG_TAG "slcan0"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#include "slcan.h"

rt_slcan_t * slcan_instance0 = NULL;

static rt_err_t slcan_instance0_rtcan_rx_call(rt_device_t dev, rt_size_t size)
{
    if(slcan_instance0 != NULL)
    {
        rt_sem_release(&(slcan_instance0->rx_sem));
    }
    return RT_EOK;
}

static rt_err_t slcan_instance0_rtserial_rx_call(rt_device_t dev, rt_size_t size)
{
    if(slcan_instance0 != NULL)
    {
        rt_sem_release(&(slcan_instance0->rx_sem));
    }
    return RT_EOK;
}


void slcan0_startup(const char * serialdev_name, const char * candev_name)
{
    if(slcan_instance0 != NULL)
    {
        rt_kprintf("slcan is run\n");
        return;
    }
    if( (serialdev_name == NULL) || (candev_name == NULL))
    {
        slcan_instance0 = slcan_instance_create("uart2", "can1");
    }else {
        slcan_instance0 = slcan_instance_create(serialdev_name, candev_name);
    }
    if(slcan_instance0 != NULL)
    {
        //can device config
        slcan_instance0->candev_rx_call = slcan_instance0_rtcan_rx_call;
        slcan_instance0->candev_oflag = RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX;

//        struct can_configure can_config = CANDEFAULTCONFIG;
//        can_config.baud_rate = CAN1MBaud;
//        rt_device_control(slcan_instance0->candev, RT_DEVICE_CTRL_CONFIG, &can_config);

        //serial device config
        slcan_instance0->serialdev_rx_call = slcan_instance0_rtserial_rx_call;
        slcan_instance0->serialdev_oflag = RT_DEVICE_FLAG_INT_RX;

//        struct serial_configure serial_config;
//        serial_config.baud_rate = BAUD_RATE_115200;
//        serial_config.data_bits = DATA_BITS_8;
//        serial_config.stop_bits = STOP_BITS_1;
//        serial_config.bufsz = RT_SERIAL_RB_BUFSZ;
//        serial_config.parity = PARITY_NONE;
//        rt_device_control(slcan_instance0->chardev, RT_DEVICE_CTRL_CONFIG, &serial_config);

//        //slcan instance config
//        slcan_instance0->slcan_baud_index = SLCAN_BAUD_500K;
//        slcan_instance0->slcan_mode_index = SLCAN_MODE_NORMAL;
//        slcan_instance0->set_flag = SLCAN_SFLAG_MODE | SLCAN_SFLAG_BUADRATE | SLCAN_SFLAG_LOG;
        slcan_instance0->set_flag = SLCAN_SFLAG_LOG;

        slcan_instance_startup(slcan_instance0,"slcan0", 2048, 20, 10);
    }else {
        rt_kprintf("slcan0 startup fail\n");
    }
    return;
}

void slcan0_stop(void)
{
    rt_kprintf("slcan0 stop\n");
    slcan_instance_delete(slcan_instance0);
    slcan_instance0 = NULL;
}



#ifdef RT_USING_FINSH
#include <finsh.h>
#include <stdlib.h>

void slcan0(uint8_t argc, char **argv)
{
    if(strcmp(argv[1],"start" ) == 0)
    {
        slcan0_startup(argv[2], argv[3]);
    }else
    if(strcmp(argv[1],"stop" ) == 0)
    {
        slcan0_stop();
    }else
    if(strcmp(argv[1],"debug" ) == 0)
    {
        int val = atoi(argv[2]);
        if(val > 0)
        {
            slcan_instance0->set_flag |= SLCAN_SFLAG_LOG;
        }else {
            slcan_instance0->set_flag &= ~SLCAN_SFLAG_LOG;
        }
        rt_kprintf("slcan0 debug set %d\n", val);
    }else {

        rt_kprintf("slcan0 usage:\n");
        rt_kprintf("slcan0 start [serial dev] [can dev]\n");
        rt_kprintf("slcan0 stop\n");
        rt_kprintf("slcan0 debug  [0-1]\n");
    }
    return;
}
MSH_CMD_EXPORT(slcan0, slcan0);


int cmd_canconfig(int argc, void **argv)
{
    //rt_device_t candev = NULL;
    rt_can_t candev = NULL;
    int num= 0;
    if (argc == 1)
    {
        candev = (rt_can_t)rt_device_find(argv[1]);
        if (!candev)
        {
            rt_kprintf(" Can't find can device %s\n", argv[1]);
            return -1;
        }
        rt_kprintf(" Finded can device: %s...", argv[1]);

        rt_kprintf("baud_rate: %d\n",candev->config.baud_rate);
        rt_kprintf("mode:      %d\n",candev->config.mode);
    }
    if (argc >= 2)
    {
        candev = (rt_can_t)rt_device_find(argv[1]);
        if (!candev)
        {
            rt_kprintf(" Can't find can device %s\n", argv[1]);
            return -1;
        }
        rt_kprintf("find device: %s\n", argv[1]);
        rt_kprintf("baud: %d\n",candev->config.baud_rate);
        rt_kprintf("mode: %d\n",candev->config.mode);

        //struct can_configure can_config = candev->config;
        int isconfig = 0;

        for(int i = 2; i < argc; i++)
        {
            if(strcmp(argv[i],"-b") == 0)
            {
                num = atoi(argv[i+1]);
                if(num > 0)
                {
                    candev->config.baud_rate = num;
                    rt_kprintf("set baud : %d\n",candev->config.baud_rate);
                    isconfig =1;
                }
            }else
            if(strcmp(argv[i],"-m") == 0)
            {
                num = atoi(argv[i+1]);
                if(num >= 0)
                {
                    candev->config.mode = num;
                    rt_kprintf("set mode : %d\n",candev->config.mode);
                    isconfig =1;
                }
            }
        }
        if(isconfig > 0)
        {
            rt_device_control((rt_device_t)candev, RT_DEVICE_CTRL_CONFIG, &(candev->config) );
        }
    }
    return 0;
}
FINSH_FUNCTION_EXPORT_ALIAS( cmd_canconfig, __cmd_canconfig, Can Device config.);
#endif





//#include <rtthread.h>
//#include <sys/socket.h> /* 使用BSD socket，需要包含socket.h头文件 */
//#include <sys/errno.h>
//#include <netdb.h>
//#include <string.h>
//#include <finsh.h>
//
//#define   BUFFSZ    (2048)
//
//
//typedef struct rt_socket_device
//{
//    const char *         device_name;
//    int                  socketfd;
//    uint16_t             port;
//    uint8_t              thread_stack[2048];
//    uint8_t              rx_ringbuffer_data[2048];
//    struct rt_ringbuffer rx_ringbuffer;
//    uint8_t              read_buffer[256];
//
//
//    struct rt_semaphore  rx_sem;
//    struct rt_mutex      tx_mutex;
//
//    struct rt_thread     thread;
//    struct rt_device     device;
//
//}rt_socket_device_t;
//
//
//void tcpserver_device_task(void *p)
//{
//    rt_socket_device_t *sdev = p;
//
//    rt_ringbuffer_init( &(sdev->rx_ringbuffer), sdev->rx_ringbuffer_data, sizeof(sdev->rx_ringbuffer_data));
//
//    rt_sem_init(&(sdev->rx_sem), sdev->device_name,  0, RT_IPC_FLAG_FIFO);
//    rt_mutex_init(&(sdev->tx_mutex), sdev->device_name, RT_IPC_FLAG_FIFO);
////
////    socklen_t sin_size;
////    int sock, connected, bytes_received;
////    struct sockaddr_in server_addr, client_addr;
////    rt_bool_t stop = RT_FALSE; /* 停止标志 */
////    int ret;
////
////    /* 一个socket在使用前，需要预先创建出来，指定SOCK_STREAM为TCP的socket */
////    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
////    {
////        /* 创建失败的错误处理 */
////        rt_kprintf("Socket error\n");
////
////        /* 释放已分配的接收缓冲 */
////        rt_free(recv_data);
////        return;
////    }
////
////    /* 初始化服务端地址 */
////    server_addr.sin_family = AF_INET;
////    server_addr.sin_port = htons(5000); /* 服务端工作的端口 */
////    server_addr.sin_addr.s_addr = INADDR_ANY;
////    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
////
////    /* 绑定socket到服务端地址 */
////    if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
////    {
////        /* 绑定失败 */
////        rt_kprintf("Unable to bind\n");
////
////        /* 释放已分配的接收缓冲 */
////        rt_free(recv_data);
////        return;
////    }
////
////    /* 在socket上进行监听 */
////    if (listen(sock, 5) == -1)
////    {
////        rt_kprintf("Listen error\n");
////
////        /* release recv buffer */
////        rt_free(recv_data);
////        return;
////    }
////
////    rt_kprintf("\nTCPServer Waiting for client on port 5000...\n");
////    while (stop != RT_TRUE)
////    {
////        sin_size = sizeof(struct sockaddr_in);
////
////        /* 接受一个客户端连接socket的请求，这个函数调用是阻塞式的 */
////        connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);
////        /* 返回的是连接成功的socket */
////        if (connected < 0)
////        {
////            rt_kprintf("accept connection failed! errno = %d\n", errno);
////            continue;
////        }
////
////        /* 接受返回的client_addr指向了客户端的地址信息 */
////        rt_kprintf("I got a connection from (%s , %d)\n",
////                   inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
////
////        /* 客户端连接的处理 */
////        while (1)
////        {
////            /* 发送数据到connected socket */
////            ret = send(connected, send_data, strlen(send_data), 0);
////            if (ret < 0)
////            {
////                /* 发送失败，关闭这个连接 */
////                closesocket(connected);
////                rt_kprintf("\nsend error,close the socket.\r\n");
////                break;
////            }
////            else if (ret == 0)
////            {
////                /* 打印send函数返回值为0的警告信息 */
////                rt_kprintf("\n Send warning,send function return 0.\r\n");
////            }
////
////            /* 从connected socket中接收数据，接收buffer是1024大小，但并不一定能够收到1024大小的数据 */
////            bytes_received = recv(connected, recv_data, BUFSZ, 0);
////            if (bytes_received < 0)
////            {
////                /* 接收失败，关闭这个connected socket */
////                closesocket(connected);
////                break;
////            }
////            else if (bytes_received == 0)
////            {
////                /* 打印recv函数返回值为0的警告信息 */
////                rt_kprintf("\nReceived warning,recv function return 0.\r\n");
////                closesocket(connected);
////                break;
////            }
////
////            /* 有接收到数据，把末端清零 */
////            recv_data[bytes_received] = '\0';
////            if (strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0)
////            {
////                /* 如果是首字母是q或Q，关闭这个连接 */
////                closesocket(connected);
////                break;
////            }
////            else if (strcmp(recv_data, "exit") == 0)
////            {
////                /* 如果接收的是exit，则关闭整个服务端 */
////                closesocket(connected);
////                stop = RT_TRUE;
////                break;
////            }
////            else
////            {
////                /* 在控制终端显示收到的数据 */
////                rt_kprintf("RECEIVED DATA = %s \n", recv_data);
////            }
////        }
////    }
////
////    /* 退出服务 */
////    closesocket(sock);
//}
//
//
//void tcpserver_device_start(const char * device_name, int port)
//{
//    if(rt_device_find(device_name) != NULL)
//    {
//        rt_kprintf("device :%s is exist!!!\n",device_name);
//        return;
//    }
//
//    rt_socket_device_t * sdevice = NULL;
//
//    sdevice = rt_malloc( sizeof(rt_socket_device_t) );
//    if(sdevice == NULL)
//    {
//        rt_kprintf("device :%s rt_malloc fail!!!\n",device_name);
//        return;
//    }
//    rt_memset(sdevice, 0, sizeof(rt_socket_device_t));
//
//    sdevice->device_name = device_name;
//    sdevice->port = port;
//
//    rt_thread_init(&(sdevice->thread), sdevice->device_name,  tcpserver_device_task, sdevice, sdevice->thread_stack, sizeof(sdevice->thread_stack), 10,20);
//
//    rt_thread_startup(&(sdevice->thread));
//
//}
//
//
//int tcpserver_device(int argc, char **argv)
//{
//    tcpserver_device_start(argv[1], atoi(argv[2]) );
//    return 0;
//}
//MSH_CMD_EXPORT(tcpserver_device, tcpserver device [device_name] [port]);
//
//




